package com.lefevre.cms.bean.staff;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;

/**
 * 系统账号表
 *
 * @author Lefevre
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("sys_users")
@Entity
@Table(name = "sys_users", uniqueConstraints = {
        @UniqueConstraint(columnNames = {"userAccount"}
        )}
)
public class SysUsers implements UserDetails, Serializable {
    private static final long serialVersionUID = -7103976496088705053L;

    @Id
    @Column(length = 50)
    @TableId(type = IdType.INPUT)
    private String userId;

    @Column(length = 30)
    private String userAccount;

    /**
     * 姓名
     */
    private String fullName;

    /**
     * 密码 BCrypt(sha256(密码原文))
     */
    private String userPassword;

    /**
     * 用户备注
     */
    private String userDesc;

    /**
     * 是否能用
     */
    private boolean enabled = true;

    /**
     * 用户的职位：比如主任、经理等
     */
    private String userDuty;

    /**
     * 是否是超级用户
     */
    private boolean issys = false;

    /**
     * 安全摘要
     **/
    @Column(length = 32)
    private String securityDigest;

    /**
     * 当前登录用户权限是否拥有本权限
     **/
    @Transient
    @TableField(exist = false)
    private boolean logonUserPermission = false;

    @Transient
    @TableField(exist = false)
    private String password;

    @Transient
    @TableField(exist = false)
    private String username;

    @Transient
    @TableField(exist = false)
    private Set<GrantedAuthority> authorities;

    /**
     * 账号过期
     */
    @Transient
    @TableField(exist = false)
    private boolean accountNonExpired;

    /**
     * 账号是否锁定
     */
    @Transient
    @TableField(exist = false)
    private boolean accountNonLocked;

    /**
     * 凭证是否过期
     */
    @Transient
    @TableField(exist = false)
    private boolean credentialsNonExpired;

    public SysUsers(String userId, String userAccount, String fullName,
                    String userPassword, String userDesc, boolean enabled, boolean issys, String securityDigest,
                    String userDuty, boolean accountNonExpired,
                    boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities) {
        if (((userAccount == null) || "".equals(userAccount)) || (userPassword == null)) {
            throw new IllegalArgumentException("不能传递null或空值的构造函数");
        }

        this.userId = userId;
        this.userAccount = userAccount;
        this.fullName = fullName;
        this.userPassword = userPassword;
        this.userDesc = userDesc;
        this.issys = issys;
        this.securityDigest = securityDigest;
        this.userDuty = userDuty;
        //     this.userDept = userDept;
        //       this.subSystem = subSystem;
        //   this.sysUsersRoleses = sysUsersRoleses;
        //     this.usersRolesSet = usersRoles;
        this.username = userAccount;
        this.password = userPassword;//加密所用的字段
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(new AuthorityComparator());
        for (GrantedAuthority grantedAuthority : authorities) {
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }
        return sortedAuthorities;
    }

    //~ Methods ========================================================================================================
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        SysUsers other = (SysUsers) obj;
        if (userId == null) {
            if (other.userId != null)
                return false;
        } else if (!userId.equals(other.userId))
            return false;
        return true;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(super.toString()).append(": ");
        sb.append("Username: ").append(this.username).append("; ");
        sb.append("Password: [PROTECTED]; ");
        sb.append("UserAccount: ").append(this.userAccount).append("; ");
        //     sb.append("UserDept: ").append(this.userDept).append("; ");
        sb.append("UserDuty: ").append(this.userDuty).append("; ");
        sb.append("UserDesc: ").append(this.userDesc).append("; ");
        //     sb.append("UserSubSystem: ").append(this.subSystem).append("; ");
        //    sb.append("UserIsSys: ").append(this.issys).append("; ");
        sb.append("Enabled: ").append(this.enabled).append("; ");
        sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
        sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
        sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
        if (null != authorities && !authorities.isEmpty()) {
            sb.append("Granted Authorities: ");
            boolean first = true;
            for (GrantedAuthority auth : authorities) {
                if (!first) {
                    sb.append(",");
                }
                first = false;
                sb.append(auth);
            }
        } else {
            sb.append("Not granted any authorities");
        }
        return sb.toString();
    }

    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            if (g2.getAuthority() == null) {
                return -1;
            }
            if (g1.getAuthority() == null) {
                return 1;
            }
            return g1.getAuthority().compareTo(g2.getAuthority());
        }
    }
}
